
let Vue; // 保存Vue构造函数，插件中要使用，不导入还能用
//VueRouter是一个插件，任何Vue的插件都必须实现一个install方法，使用的时候用Vue.use();
class VueRouter {
    constructor(options) {
        this.$options = options;
        // 定义响应式的属性current
        const initial = window.location.hash.slice(1) || '/'
        //当路由变化的时候，Vue.util.defineReactive把vue-router 的current属性变成响应式的
        // 当vue-router 的current变化的时候，由于router-view使用到了vue-router，所以router-view会重新渲染。
        Vue.util.defineReactive(this, 'current', initial)
        // 监听hashchange事件
        window.addEventListener('hashchange', this.onHashChange.bind(this))
        window.addEventListener('load', this.onHashChange.bind(this))
    }
    onHashChange() {
        this.current = window.location.hash.slice(1)
    }
}

// 插件：实现install⽅法，注册$router
VueRouter.install = function (_Vue) {
    // 引⽤构造函数，VueRouter中要使⽤
    Vue = _Vue;

    // 任务1：挂载$router
    Vue.mixin({//Vue.mixin 全局混入的话，就可以在任意vue实例构建的时候都执行。
        beforeCreate() {//在new Vue的时候会执行beforeCreate
            // 在创建Vue根组件的时候配置router选项，然后通过this.$options.router拿到router实例
            if (this.$options.router) {
                // vm.$router
                Vue.prototype.$router = this.$options.router;
            }
        }
    });

    // 任务2：实现两个全局组件router-link和router-view
    Vue.component('router-link', Link)
    Vue.component('router-view', View)
};
// router-link 组件：
const Link = {
    props: {
        to: String,
        required: true,
    },
    render(h) {
        // return <a href={'#'+this.to}>{this.$slots.default}</a>;
        return h('a', {
            attrs: {
                href: '#' + this.to
            }
        }, [
            this.$slots.default
        ])
    }
}

//router-view 组件：
const View = {
    render(h) {
        // 动态获取对应组件
        let component = null;
        //注意所有vue实例都可以拿到this.$router，包括router-view 组件。这个设计很巧妙
        const route = this.$router.$options.routes.find(route => route.path === this.$router.current)
        if(route) component = route.component
        return h(component);
    }
}

export default VueRouter;


